package com.imu.purse.api.controller.trade;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.imu.common.annotation.IgnoreAuth;
import com.imu.common.exception.ErrorDesc;
import com.imu.common.exception.ErrorUtil;
import com.imu.common.utils.IPUtils;
import com.imu.common.utils.PhoneUtil;
import com.imu.common.utils.R;
import com.imu.common.validator.ValidatorUtils;
import com.imu.constant.Constant;
import com.imu.enums.CheckType;
import com.imu.purse.api.controller.ApiAbstractController;
import com.imu.purse.modules.app.entity.ImuUserEntity;
import com.imu.purse.modules.app.entity.RateEntity;
import com.imu.purse.modules.app.entity.UserCheckEntity;
import com.imu.purse.modules.app.service.CoreService;
import com.imu.purse.modules.app.service.ImuUserService;
import com.imu.purse.modules.app.service.RateService;
import com.imu.purse.modules.app.service.UserCheckService;
import com.imu.purse.modules.base.entity.DictInfo;
import com.imu.purse.modules.base.entity.SysConfigEntity;
import com.imu.purse.modules.base.service.DictInfoService;
import com.imu.purse.modules.base.service.SysConfigService;
import com.imu.purse.modules.bitcoin.YtfcoinApi;
import com.imu.purse.modules.trade.entity.FundEntity;
import com.imu.purse.modules.trade.entity.TradeInfoEntity;
import com.imu.purse.modules.trade.form.*;
import com.imu.purse.modules.trade.service.FundService;
import com.imu.purse.modules.trade.service.TradeInfoService;
import com.imu.purse.modules.trade.service.TradeLogService;
import com.imu.purse.produce.YtfTransProduce;
import com.imu.security.SessionKeys;
import com.imu.security.SessionTokenProviderFactory;
import com.imu.utils.RSASignature;
import com.imu.utils.RedisLockUtil;
import com.xiaoleilu.hutool.bean.BeanUtil;
import com.xiaoleilu.hutool.log.Log;
import com.xiaoleilu.hutool.log.LogFactory;
import com.xiaoleilu.hutool.util.StrUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.web3j.abi.datatypes.Bool;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 交易接口
 * @author sunhongwei
 * @email sunhongwei@gmail.com
 * @date 2018-03-22 17:27
 */
@RestController
@RequestMapping("/api/trade")
@Api(tags="交易接口")
public class ApiTradeController extends ApiAbstractController
{


    /**
     * 合赢系统获取IMU国际钱包的IMU，GET的数量
     * @param request
     * @param phone
     * @return
     */
    public R getFundByPhone(HttpServletRequest request,@PathVariable("phone") String phone){
        //获取系统参数的可调用的IP地址
        SysConfigEntity sysConfigEntity = sysConfigService.findByKey(Constant.HY_IP);
        //获取调用服务器的IP地址
        String remoteIp = IPUtils.getIpAddr(request);
        logger.info("getFundByPhone remoteIp ============== " + remoteIp);

        if(sysConfigEntity == null || sysConfigEntity.getValue().indexOf(remoteIp) == -1){
            return  R.error(0,"IP地址不合法");
        }
        if(StrUtil.isEmpty(phone)){
            return R.error(0,"phone不能为空");
        }
        //校验IP地址有效性
        ImuUserEntity userEntity = userService.queryByMobile(phone);
        if(userEntity == null){
            return R.error(0,"手机号码无效");
        }
        //根据用户ID获取该用户的资金信息
        FundEntity fundEntity = fundService.findByUserId(userEntity.getId());
        if(fundEntity == null){
            return R.error(0,"该用户还未在IMU注册或登录");
        }
        return R.ok(1).put("IMU",fundEntity.getMoney()).put("GET",fundEntity.getEth());
    }
    /**
     * 合赢系统下单调用IMU国际钱包接口
     * TradeLogEntity dto 
     */
    @IgnoreAuth
    @PostMapping("/convsion")
    @ApiOperation(value = "兑换")
    @ApiImplicitParams({
    	@ApiImplicitParam(paramType = "body",   dataType="ConversionForm", name = "dto",    value = "转账", required = true)
    })
    public R convsion(@RequestBody ConversionForm dto, HttpServletRequest request)
    {
        //获取系统参数的可调用的IP地址
        SysConfigEntity sysConfigEntity = sysConfigService.findByKey(Constant.HY_IP);
//        //获取调用服务器的IP地址
        String remoteIp = IPUtils.getIpAddr(request);
        logger.info("convsion remoteIp ============== " + remoteIp);
        if(sysConfigEntity == null || sysConfigEntity.getValue().indexOf(remoteIp) == -1){
            return  R.error(0,"IP地址不合法");
        }
    	//表单校验
        ValidatorUtils.validateEntity(dto);
        String  sign = request.getHeader(SessionKeys.SIGN.toString());
//        if(!RSASignature.verifySign(JSON.toJSONString(dto),sign, this.pubKey))
//        {
//        	return R.error(0,"签名错误");
//        }

        //校验付款账号是否存在
        ImuUserEntity userEntity = userService.queryByMobile(dto.getPayAccount());
        if(userEntity == null){
            return R.error(0,"该账号不合法");
        }

        long startNum = System.currentTimeMillis();
        //获取一次交易时长 默认为2分钟
        long defaultNum = 2l * 60l  * 1000l;
        while (System.currentTimeMillis() - startNum < defaultNum) {
            if (RedisLockUtil.lock("lock:user:" + userEntity.getId(), 60)) {
                return tradeLogService.conversion(dto, userEntity.getId(),sign);
            }
        }
        RedisLockUtil.unLock("lock:user:" + userEntity.getId());
        return R.ok(1);
    }

    /**
     * 合赢系统合营分兑换IMU GET
     * TradeLogEntity dto
     */
    @IgnoreAuth
    @PostMapping("/exchange")
    @ApiOperation(value = "合营分兑换")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "body",   dataType="ExchangeForm", name = "dto",    value = "转账", required = true)
    })
    public R exchange(@RequestBody ExchangeForm dto, HttpServletRequest request)
    {
        //获取系统参数的可调用的IP地址
       SysConfigEntity sysConfigEntity = sysConfigService.findByKey(Constant.HY_IP);

//        //获取调用服务器的IP地址
        String remoteIp = IPUtils.getIpAddr(request);
        logger.info("exchange remoteIp ============== " + remoteIp);
        if(sysConfigEntity == null || sysConfigEntity.getValue().indexOf(remoteIp) == -1){
            return  R.error(0,"IP地址不合法");
        }
        //表单校验
        ValidatorUtils.validateEntity(dto);
        String  sign = request.getHeader(SessionKeys.SIGN.toString());
//        if(!RSASignature.verifySign(JSON.toJSONString(dto),sign, this.pubKey))
//        {
//            return R.error(0,"签名错误");
//        }

        //校验付款账号是否存在
        ImuUserEntity userEntity = userService.queryByMobile(dto.getPayAccount());
        if(userEntity == null){
            return R.error(0,"该账号不合法");
        }

        long startNum = System.currentTimeMillis();
        //获取一次交易时长 默认为2分钟
        long defaultNum = 2l * 60l  * 1000l;
        while (System.currentTimeMillis() - startNum < defaultNum) {
            if (RedisLockUtil.lock("lock:user:" + userEntity.getId(), 60)) {
                return tradeLogService.exchange(dto, userEntity.getId(),sign);
            }
        }
        RedisLockUtil.unLock("lock:user:" + userEntity.getId());
        return R.ok(1);
    }

    @IgnoreAuth
    @GetMapping("/convsion")
    @ApiOperation(value = "查询兑换订单信息")
    public R checkConvsion(@RequestParam("payAccount") String payAccount,@RequestParam("orderNo") String orderNo)
    {
        //获取系统参数的可调用的IP地址
//       SysConfigEntity sysConfigEntity = sysConfigService.findByKey(Constant.HY_IP);
//        //获取调用服务器的IP地址
//        String remoteIp = IPUtils.getIpAddr(request);
//        if(sysConfigEntity == null || sysConfigEntity.getValue().indexOf(remoteIp) == -1){
//            return  R.error(0,"IP地址不合法");
//        }

        if(null == payAccount || null == orderNo)
            return R.error(0,"输入参数不合法");

        //校验付款账号是否存在
        ImuUserEntity userEntity = userService.queryByMobile(payAccount);
        if(userEntity == null){
            return R.error(0,"该账号不合法");
        }

        int result = tradeLogService.checkConvsion(orderNo, userEntity.getId());
        if(result>0) {
            return R.ok(1);
        } else {
            return R.error(0,"未查询到订单");
        }
    }

    /**
     * 转账记录
     */
    @PostMapping("show")
    @ApiOperation(value = "交易记录",notes = "交易记录说明")
    @ApiImplicitParams({
    	@ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SECRET",  value = "密钥",  required = true),
        @ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SESSION", value = "会话",  required = true)
    })
    public R show(@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token,@RequestBody TradeInfoForm form,
    		HttpServletRequest request)
    {
		//判断Session 是否存在
        String uid = SessionTokenProviderFactory.getSessionTokenProvider().getUserId(secret, token);
        if(StrUtil.isBlank(uid))
    	{
        	return ErrorUtil.errorMesg(request,ErrorDesc.SESSION_EMPTY);
    	}
        /*TradeInfoEntity info = new TradeInfoEntity();
        info.setPage(page);
        info.setLimit(rows);
        info.setStime(s);
        info.setEtime(e);
        info.setPayUserId(Long.valueOf(uid));
        info.setOrderType(t);*/

        form.setPayUserId(Long.valueOf(uid));
        TradeInfoEntity info = new TradeInfoEntity();
        BeanUtil.copyProperties(form,info);
        //构建查询时间
        getQueryDate(info,form);
        /*if(info.getPage() != null && info.getPage() > 0){
            info.setPage(info.getPage()-1);
        }*/
        List<TradeInfoEntity> dtos = tradeInfoService.queryList(info);
		PageInfo<TradeInfoEntity> pages = new PageInfo<TradeInfoEntity>(dtos);
		R data = R.ok(1);
		data.put("aaData", pages.getList());
		data.put("sEcho", form.getDraw());
		data.put("iTotalRecords", pages.getTotal());
		data.put("iTotalDisplayRecords", pages.getTotal());

        return data;
    }
    @PostMapping("scanTrans")
    @ApiOperation(value = "站内互转",notes = "站内互转")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType="String",    name = "X-IMU-SECRET",  value = "密钥",  required = true),
            @ApiImplicitParam(paramType = "header", dataType="String",    name = "X-IMU-SESSION", value = "会话",  required = true),
            @ApiImplicitParam(paramType = "header", dataType="String",    name = "X-IMU-SIGN", 	value = "签名",  	  required = true),
            @ApiImplicitParam(paramType = "body",   dataType="ScanTransForm", name = "form", 		value = "转账",	  required = true)
    })
    public R scanTrans(HttpServletRequest request,@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token, @RequestHeader("X-IMU-SIGN") String sign, @RequestBody ScanTransForm form) {
        //是否允许转账
        SysConfigEntity sysConfigEntity = sysConfigService.findByKey("TRANS_KEY");
        if(sysConfigEntity != null && sysConfigEntity.getValue().equals("0")){
            return ErrorUtil.errorMesg(request,ErrorDesc.TRANS_ENABLE_KEY);
        }
        //表单校验
        ValidatorUtils.validateEntity(form);
        //判断Session 是否存在
        String uid = SessionTokenProviderFactory.getSessionTokenProvider().getUserId(secret, token);
        if (StrUtil.isBlank(uid)) {
            return ErrorUtil.errorMesg(request, ErrorDesc.SESSION_EMPTY);
        }

        //校验签名信息
        if (!RSASignature.verifySign(JSON.toJSONString(form), sign, this.pubKey)) {
            return ErrorUtil.errorMesg(request, ErrorDesc.SIGN_VERIFY_ERR);
        }

        if(form.getYtfType() == null || (form.getYtfType() != 0 && form.getYtfType() != 1
        && form.getYtfType() != 2 && form.getYtfType() != 3 && form.getYtfType() != 4)){
            return ErrorUtil.errorMesg(request,ErrorDesc.YTF_TYPE_ERROR);
        }
        //根据id获取该用户的手机号码
        ImuUserEntity payUser = userService.findById(Long.valueOf(uid));

        if(payUser.getState() == null  || payUser.getState() == 0){//账号被禁用
            return ErrorUtil.errorMesg(request,ErrorDesc.ACC_SUSPEND);
        }
        //判断用户是否可以转账标识
        if(payUser.getStatetrans() != null && "0".equals(payUser.getStatetrans().toString())) return ErrorUtil.errorMesg(request,ErrorDesc.USER_TRANS_ENABLE);

        if(payUser.getPhone().equals(form.getRecAccount())){//目标不允许为转账人
            return ErrorUtil.errorMesg(request,ErrorDesc.TRADE_SAME_ACCOUNT);
        }
        FundEntity payFund = fundService.findByUserId(payUser.getId());
        if(form.getRecAccount().equals(payFund.getMoneyAddress())){//目标不允许为转账人
            return ErrorUtil.errorMesg(request,ErrorDesc.TRADE_SAME_ACCOUNT);
        }
        boolean outFlag = true; //外部转账标记 默认为外部转账
        ImuUserEntity recUser = null; //接受用户信息
        FundEntity rFund = null; ///接受用户资金信息
        String moneyAddress = form.getRecAccount();
        if(PhoneUtil.validate(moneyAddress)){//如果是手机号码
            //根据手机号码获取接受人信息
            recUser = userService.queryByMobile(moneyAddress);
            if(recUser == null){
                return ErrorUtil.errorMesg(request,ErrorDesc.MONEY_PACK_ADDR_INVALIDE);
            }
            //根据用户获取对应用户资金信息
            rFund = fundService.findByUserId(recUser.getId());
            moneyAddress = rFund.getMoneyAddress();
            outFlag = false;
        }else{
            //return ErrorUtil.errorMesg(request,ErrorDesc.MONEY_PACK_ADDR_INVALIDE);
            //根据地址获取用户ID，首先在缓存中获取
            Long cacheUserId = fundService.findUserIdByAdress(moneyAddress);
            if(cacheUserId != null){//内部转账
                recUser = userService.findById(cacheUserId);
                outFlag = false;
            }
        }

        //获取缓存注册时钱包地址
        String payAddress = coreService.getCoreAddress(Long.valueOf(uid));

        //校验支付密码正确性
        if(payUser == null || StrUtil.isBlank(payUser.getPayPwd())
                || !payUser.getPayPwd().equals(new Sha256Hash(form.getPayPwd()).toHex()))
        {
            return ErrorUtil.errorMesg(request,ErrorDesc.TRADE_PWD_ERROR);
        }

        String picPass = form.getCode().toLowerCase();
        //验证图片验证码是否正确
        if(StrUtil.isEmpty(redisTemplate.opsForValue().get(picPass))){
            return ErrorUtil.errorMesg(request,ErrorDesc.PHOTO_ACODE_ERROR);
        }
        //如果手势密码不为空，则校验手势密码
        R r = checkHpwd(request,form,uid);
        if(r.get("code") != null && Integer.valueOf(r.get("code").toString()) !=1){
            return r;
        }
        //2018-06-21 15:00:00 外部转账暂时不允许
        if(outFlag && !checkTranToOut()){//不允许转出其他核心钱包
            return ErrorUtil.errorMesg(request,ErrorDesc.TRANS_OUT_ERROR);
        }
        long startNum = System.currentTimeMillis();
        //获取一次交易时长 默认为2分钟
        long defaultNum = 2l * 60l * 1000l;
        boolean flag = redisTemplate.opsForValue().setIfAbsent(Constant.TRANS_CONSUMER_TIME,defaultNum+"");
        if(!flag){
            defaultNum = Long.valueOf(redisTemplate.opsForValue().get(Constant.TRANS_CONSUMER_TIME));
        }
        boolean tranFlag = false;
        form.setFee(new BigDecimal(0));//默认为内部转账，汇率为0
        while (System.currentTimeMillis() - startNum < defaultNum) {
            if(RedisLockUtil.lock("lock:user:" + uid,60)) {
                if(outFlag){//外部转账 才需要考虑汇率的问题，注意
                    if(form.getYtfType() != 0){
                        RedisLockUtil.unLock("lock:user:" + uid);
                        return ErrorUtil.errorMesg(request, ErrorDesc.OUT_IMU_ENABLE);
                    }
                    /*if(form.getMoney().compareTo(new BigDecimal(10)) > 0){
                        return ErrorUtil.errorMesg(request,ErrorDesc.ONE_TRANS_NUM);
                    }*/
                   //初始化汇率
                    initRate(form);
                    Map<String,Object> rMap = getMaxDayMoney(payUser.getId(),form.getMoney(),form.getFee());
                    boolean aFlag = (Boolean)rMap.get(Constant.MAX_OUT.MAX_OUT_FLAG);
                    if(!aFlag){
                        RedisLockUtil.unLock("lock:user:" + uid);
                        return R.error(ErrorDesc.DAY_OUT_MAX_VALUE.getCode(),ErrorDesc.DAY_OUT_MAX_VALUE.getMsg() + rMap.get(Constant.MAX_OUT.MAX_OUT) + "IMU");
                    }

                }
                //获取支付人金额信息
                payFund = fundService.findByUserId(payUser.getId());

                //转出用户，接受用户最新的金额
                Map<String,BigDecimal> moneyMap = Maps.newHashMap();
                moneyMap.put("payMoney",new BigDecimal(0));
                moneyMap.put("recMoney",new BigDecimal(0));
                //获取指定钱包的金额
                //手续费为用户实际转出金额的百分比
                if (!initMoney(payFund,rFund,form,moneyMap)) { //不允许转账
                    RedisLockUtil.unLock("lock:user:" + uid);
                    return ErrorUtil.errorMesg(request, ErrorDesc.MONEY_PACK_LIMIT);
                }

                form.setOutFlag(outFlag);
                form.setPayPhone(payUser.getPhone());
                form.setPayAddr(payFund.getMoneyAddress());
                form.setPayUserId(payUser.getId());
                form.setRecPhone(recUser == null ? null : recUser.getPhone());
                form.setRecAddr(moneyAddress);
                form.setRecUserId(recUser == null ? null : recUser.getId());
                form.setCoreAddr(payAddress);
                //调用转账接口
                tradeInfoService.scanTrans(form,moneyMap);
                if (outFlag) {
                    TransForm transForm = new TransForm();
                    BeanUtil.copyProperties(form, transForm);
                    //转出的时候，都是通过我们这边大钱包往外面转，也就是from为
                    //打钱包地址
                    transForm.setPayAddr(Constant.IMU_MONEY_INNER_ADDRESS);
                    transForm.setPayPhone(Constant.IMU_MONEY_INNER_PWD);
                    //从A1转到B1，统一将ytfType定义为0
                    transForm.setYtfType(0);
                    ytfTransProduce.sendData(transForm);
                }
                tranFlag = true;
                break;
            }else{
                try {
                    TimeUnit.MILLISECONDS.sleep(10);
                } catch (InterruptedException e) {
                    log.error(e);
                }
            }
        }
        if(!tranFlag){
            RedisLockUtil.unLock("lock:user:" + uid);
            return ErrorUtil.errorMesg(request,ErrorDesc.SYSTEM_BUSY);
        }
        RedisLockUtil.unLock("lock:user:" + uid);
        redisTemplate.delete(picPass);
        return R.ok(1);
    }
    /**
     * 构建查询时间
     * @param entity
     * @param form
     */
    private void getQueryDate(TradeInfoEntity entity,TradeInfoForm form){
    	Calendar cal = Calendar.getInstance();
    	//构建开始时间
    	cal.set(form.getQtime(), 0,1,0,0,0);
    	entity.setStartTime(cal.getTime());
    	//构建结束时间
    	cal.set(form.getQtime(), 11,31,23,59,59);
    	entity.setEndTime(cal.getTime());
    	
    }

    /**
     * 当前用户本日是否超额
     * @param userId
     * @param money
     * @param fee
     * @return
     */
    private Map<String,Object> getMaxDayMoney(Long userId,BigDecimal money,BigDecimal fee){
        Map<String,Object> rMap = Maps.newHashMap();
        rMap.put(Constant.MAX_OUT.MAX_OUT,new BigDecimal(10));//默认为一天10个
        rMap.put(Constant.MAX_OUT.MAX_OUT_FLAG,false);//默认不允许转出
        //获取一天最大的限额
        BigDecimal dayMoney = Constant.DAY_MONEY;
        List<DictInfo> dictList = dictInfoService.findCahceByCode("TRANS_INFO_MAX");
        if(!CollectionUtils.isEmpty(dictList)) {
            for (DictInfo dic : dictList) {
                if (dic.getLabel().equals("MAX_VALUE")) {
                    dayMoney = new BigDecimal(dic.getValue());
                    rMap.put(Constant.MAX_OUT.MAX_OUT,dayMoney);
                    break;
                }
            }
        }

        //获取该用户当日已交易的imu的个数
        BigDecimal yetMoney = tradeInfoService.getMoneyByUIdAndDay(userId,new Date());
        yetMoney = (yetMoney == null ? new BigDecimal(0) : yetMoney);
        if(dayMoney.compareTo(yetMoney.add(money)) >= 0){
            rMap.put(Constant.MAX_OUT.MAX_OUT_FLAG,true);
        }
        return rMap;
    }

    /**
     * 转账记录
     */
    @PostMapping("showApp")
    @ApiOperation(value = "交易记录",notes = "交易记录说明")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SECRET",  value = "密钥",  required = true),
            @ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SESSION", value = "会话",  required = true)
    })
    public R showApp(@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token,@RequestBody TradeInfoForm form,
                  HttpServletRequest request)
    {
        //判断Session 是否存在
        String uid = SessionTokenProviderFactory.getSessionTokenProvider().getUserId(secret, token);
        if(StrUtil.isBlank(uid))
        {
            return ErrorUtil.errorMesg(request,ErrorDesc.SESSION_EMPTY);
        }


        form.setPayUserId(Long.valueOf(uid));
        TradeInfoEntity info = new TradeInfoEntity();

        BeanUtil.copyProperties(form,info);
        //默认一次请求50条
        info.setLimit(50);
        /*if(info.getPage() != null && info.getPage() > 0){
            info.setPage(info.getPage()-1);
        }*/
        //构建查询时间
        getQueryDate(info,form);
        List<TradeInfoEntity> dtos = tradeInfoService.queryList(info);
        PageInfo<TradeInfoEntity> pages = new PageInfo<TradeInfoEntity>(dtos);
        R data = R.ok(1);
        data.put("data",pages.getList());
        data.put("page",pages.getPageNum());
        data.put("lastFlag",pages.isIsLastPage());
        return data;
    }

    /**
     * 根据id获取交易详情
     */
    @GetMapping("getTransDetailById/{id}")
    @ApiOperation(value = "根据id获取交易详情",notes = "根据id获取交易详情")
    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SECRET",  value = "密钥",  required = true),
            @ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SESSION", value = "会话",  required = true)
    })
    public R getTransDetailById(@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token,@PathVariable("id") Long id,
                     HttpServletRequest request)
    {
        //判断Session 是否存在
        String uid = SessionTokenProviderFactory.getSessionTokenProvider().getUserId(secret, token);
        if(StrUtil.isBlank(uid))
        {
            return ErrorUtil.errorMesg(request,ErrorDesc.SESSION_EMPTY);
        }

        TradeInfoEntity info = tradeInfoService.findById(id);

        return R.ok(1).put("data",info);
    }

    @ApiImplicitParams({
            @ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SECRET",  value = "密钥",  required = true),
            @ApiImplicitParam(paramType = "header", dataType="String",  name = "X-IMU-SESSION", value = "会话",  required = true),
            @ApiImplicitParam(paramType = "body", dataType = "String", name = "address" ,value = "接受目标", required = true)
    })
    @GetMapping("checkAddress/{address}")
    public R checkAddress(HttpServletRequest request,@RequestHeader("X-IMU-SECRET") String secret, @RequestHeader("X-IMU-SESSION") String token,@PathVariable("address") String address) {
        //判断Session 是否存在
        String uid = SessionTokenProviderFactory.getSessionTokenProvider().getUserId(secret, token);
        if (StrUtil.isBlank(uid)) {
            return ErrorUtil.errorMesg(request, ErrorDesc.SESSION_EMPTY);
        }
        if (StrUtil.isBlank(address)) {
            return ErrorUtil.errorMesg(request, ErrorDesc.MONEY_PACK_ADDR_INVALIDE);
        }

        // 获取目标的用户信息  先差缓存，再查数据库
        ImuUserEntity recUser = userService.queryByMobile(address);
        if (recUser == null) {//不存在，可能是一个外部钱包地址或者是一个无效的手机号码
            //根据该地址查找缓存中是否存在该数据
            Long userId = fundService.findUserIdByAdress(address);
            if (userId == null && address.startsWith(Constant.YTF_PREFIX)) { //可能是一个外部钱包地址
                return R.ok(1).put("outFlag", 1);
            } else if (userId == null && !address.startsWith(Constant.YTF_PREFIX)) {
                return ErrorUtil.errorMesg(request, ErrorDesc.MONEY_PACK_ADDR_INVALIDE);
            }
        }
        return R.ok(1).put("outFlag",0);
    }
    
    /**
     * 校验是否允许转出到外部
     * @return
     */
    private boolean checkTranToOut(){
        boolean outFlag = true; //默认允许转出到其他核心钱包
        List<DictInfo> dictList = dictInfoService.findCahceByCode("TRANS_OUT_FLAG");
        if(!CollectionUtils.isEmpty(dictList)) {
            for (DictInfo dic : dictList) {
                if (dic.getLabel().equals("OUT_FLAG")) {
                    if(Integer.valueOf(dic.getValue()) == 0){
                        outFlag = false;
                    }
                    break;
                }
            }
        }
        return outFlag;
    }

    /**
     * 初始化汇率
     * @param form
     */
    private void initRate(ScanTransForm form){
        //获取当前的汇率
        BigDecimal rate = Constant.DEFAULT_RATE;
        //判断用户余额 总金额-冻结金额
        RateEntity entity = new RateEntity();
        entity.setRate(form.getMoney());
        entity = rateService.selectByRate(entity);
        if (null != entity) {//
            rate = entity.getRate();
        }
        form.setFee(rate);
    }

    /**
     * 解析是否允许转账
     * @param payFund
     * @param  recFund
     * @param form
     * @param  moneyMap
     * @return
     */
    private Boolean initMoney(FundEntity payFund,FundEntity recFund,ScanTransForm form,Map<String,BigDecimal> moneyMap){
        Boolean transFlag = false;//转账标记 默认不允许转账
        BigDecimal money = new BigDecimal(0);
        switch (form.getYtfType()){
            case 0 : //IMU
                money = payFund.getMoney().subtract(payFund.getFrozenMoney())
                        .subtract(form.getFee()).subtract(form.getMoney());
                moneyMap.put("payMoney",payFund.getMoney().subtract(payFund.getFrozenMoney()));
                if(recFund != null){
                    moneyMap.put("recMoney",recFund.getMoney().subtract(recFund.getFrozenMoney()));
                }
                break;
            case 2 : //易买宝
                money = payFund.getBj().subtract(form.getMoney()).subtract(form.getFee());
                moneyMap.put("payMoney",payFund.getBj());
                if(recFund != null){
                    moneyMap.put("recMoney",recFund.getBj());
                }
                break;
            case 3 : //KCT or KTC
                money = payFund.getLockico().subtract(form.getMoney()).subtract(form.getFee());
                moneyMap.put("payMoney",payFund.getLockico());
                if(recFund != null){
                    moneyMap.put("recMoney",recFund.getLockico());
                }
                break;
            case 4: //ETH 即GET
                money  = payFund.getLocketh().subtract(form.getMoney()).subtract(form.getFee());
                moneyMap.put("payMoney",payFund.getLocketh());
                if(recFund != null){
                    moneyMap.put("recMoney",recFund.getLocketh());
                }
                break;
            default:
                break;
        }
        if(money.compareTo(new BigDecimal(0)) >= 0){
            transFlag = true;
        }

        return transFlag;
    }

    /**
     * 校验手势密码
     * @param request
     * @param form
     * @param uid
     * @return
     */
    private R checkHpwd(HttpServletRequest request,ScanTransForm form,String uid){
        if(StrUtil.isNotEmpty(form.getHpwd())){
            if(StrUtil.isEmpty(form.getImei())){
                return ErrorUtil.errorMesg(request,ErrorDesc.IME_EMPTY);
            }
            UserCheckEntity checkEntity = userCheckService.findByUserId(Long.valueOf(uid));
            if(checkEntity == null || checkEntity.getCheckType() == null ||
                    checkEntity.getCheckType() != CheckType.HAND.getType()){
                return ErrorUtil.errorMesg(request,ErrorDesc.CHECK_TYPE_ERROR);
            }/*else if(checkEntity == null || !form.getImei().equals(checkEntity.getImei())){
                return ErrorUtil.errorMesg(request,ErrorDesc.IME_ERROR);
            }*/ else if(checkEntity == null || !form.getHpwd().equals(checkEntity.getCheckValue())){
                return ErrorUtil.errorMesg(request,ErrorDesc.HPWD_ERROR);
            }
        }
        return R.ok(1);
    }
    /****
     *公钥解密
     */
    @Value("${app.pay.pub-key}")
    private String pubKey;

	@Autowired
	private ImuUserService userService;

    @Autowired
    private TradeLogService tradeLogService;

    @Autowired
    private TradeInfoService tradeInfoService;
    
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    
    @Autowired
    private FundService fundService;
    
    @Autowired
    private YtfcoinApi ytfcoinApi;

    
    @Autowired
    private RateService rateService;

    @Autowired
    private YtfTransProduce ytfTransProduce;

    @Autowired
    private DictInfoService dictInfoService;

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private CoreService coreService;

    @Autowired
    private UserCheckService userCheckService;

    private static final Log log = LogFactory.get(ApiTradeController.class);

    public static void main(String[] args){
        BigDecimal totalMoeny = new BigDecimal(100.85);
        BigDecimal gbToRmb = new BigDecimal(0.8181);
        BigDecimal divRmb = totalMoeny.multiply(gbToRmb);
        double result = divRmb.setScale(8,BigDecimal.ROUND_HALF_DOWN).doubleValue();
        //divRmb.setScale(8,BigDecimal.ROUND_DOWN);
        System.out.println(result);

        BigDecimal money = new BigDecimal(0.20626346);
        BigDecimal imuToRmb = new BigDecimal(400.0);
        double e = money.multiply(imuToRmb).setScale(8,BigDecimal.ROUND_HALF_DOWN).doubleValue();
        System.out.println(e);

        System.out.println(divRmb.divide(imuToRmb,8,BigDecimal.ROUND_HALF_UP));

        System.out.println(Long.valueOf("147048",16));

        System.out.println("qqq".equals(null));
    }
}
